import { ResourceDirectoryEntry } from "./ResourceDirectoryEntry.ts";


/**
 * 表示一个资源目录，封装了有关目录结构和内容的详细信息。
 * 这包括关于目录的元数据，如版本信息和时间戳，
 * 以及关于目录中特定条目（包括命名和未命名条目）的详细信息。
 * @author tongxin
 * @date 2024/4/20 22:12
 */
export class ResourceDirectoryTable {

  /**
   * 常量，对象长度
   */
  static LENGTH = 16 as const;
  /**
   * 特性标志，
   */
  characteristics?: number;

  /**
   * 时间日期戳，记录资源目录创建或最后修改的时间
   */
  timeDateStamp?: number;

  /**
   * 主版本号，标识资源目录所遵循的主要版本规范
   */
  majorVersion?: number;

  /**
   * 次版本号，标识资源目录所遵循的次要版本规范
   */
  minorVersion?: number;

  /**
   * 命名条目的数量，表示目录中具有名称的资源条目总数
   */
  numberOfNamedEntries?: number;

  /**
   * 无名条目的数量，表示目录中通过ID标识而非名称标识的资源条目总数
   */
  numberOfIdEntries?: number;

  /**
   * 存储资源目录条目的映射表，键为条目的唯一标识（长整型），值为ResourceDirectoryEntry对象
   */
  entries: Record<number, ResourceDirectoryEntry> = {};
  dataReader: IPEFileReader;
  offset: number;
  baseOffset?: number


  constructor(dataReader: IPEFileReader, baseOffset?: number) {
    this.dataReader = dataReader;
    this.offset = dataReader.getOffset();
    if (baseOffset) {
      this.baseOffset = baseOffset;
    }
  }

  async read() {
    this.dataReader.setOffset(this.offset);
    const byteArray: IByteArray = await this.dataReader.read(ResourceDirectoryTable.LENGTH);
    this.characteristics = byteArray.readDWord();
    this.timeDateStamp = byteArray.readDWord();
    this.majorVersion = byteArray.readWord();
    this.minorVersion = byteArray.readWord();
    this.numberOfNamedEntries = byteArray.readWord();
    this.numberOfIdEntries = byteArray.readWord();
    const count: number = this.numberOfNamedEntries + this.numberOfIdEntries;
    for (let i = 0; i < count; i++) {
      this.dataReader.setOffset(this.offset + ResourceDirectoryTable.LENGTH + ResourceDirectoryEntry.LENGTH * i);
      // 读取资源目录项
      const entry: ResourceDirectoryEntry = new ResourceDirectoryEntry(this.dataReader, this.baseOffset || this.offset);
      await entry.read();
      this.entries[entry.integerId!] = entry;
    }
  }

  getResourceDirectoryEntry(id: number): ResourceDirectoryEntry {
    return this.entries[id];
  }
}
